<template>
  <view
    class="image-preview"
    v-if="visible"
    @touchmove.prevent
    @tap="closePreviewOnBg"
  >
    <!-- 顶部计数和关闭按钮 -->
    <view class="preview-header" v-if="showCounter || showCloseButton">
      <view class="preview-count" v-if="showCounter">
        {{ currentIndex + 1 }}/{{ images.length }}
      </view>
      <view class="preview-close" @tap.stop="close" v-if="showCloseButton"
        >×</view
      >
    </view>

    <!-- 图片轮播 -->
    <swiper
      class="preview-swiper"
      :current="currentIndex"
      @change="onSwiperChange"
      @tap.stop
    >
      <swiper-item v-for="(item, index) in images" :key="index">
        <view
          class="zoom-container"
          @touchstart="touchStart($event, index)"
          @touchmove="touchMove($event, index)"
          @touchend="touchEnd"
          @tap.stop="handleTap($event, index)"
        >
          <image 
            class="preview-image" 
            :src="item" 
            mode="aspectFit"
            :style="{
              transform:
                index === currentIndex
                  ? `scale(${scaleValues[index] || 1})`
                  : 'scale(1)',
              transition: isScaling ? 'none' : 'transform 0.3s',
            }"
            @load="onImageLoad($event, index)"
          ></image>
        </view>
      </swiper-item>
    </swiper>

    <!-- 底部工具栏 -->
    <view class="preview-footer" v-if="showDownload">
      <view class="download-btn" @tap.stop="downloadImage">
        <image
          src="/static/image/xz.png"
          mode="aspectFit"
          style="width: 40rpx; height: 40rpx"
        ></image>
        <text>保存图片</text>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  name: "ImagePreview",
  props: {
    // 控制预览是否可见
    visible: {
      type: Boolean,
      default: false,
    },
    // 图片数组
    images: {
      type: Array,
      default: () => [],
    },
    // 当前显示的图片索引
    defaultIndex: {
      type: Number,
      default: 0,
    },
    // 是否显示计数器
    showCounter: {
      type: Boolean,
      default: true,
    },
    // 是否显示关闭按钮
    showCloseButton: {
      type: Boolean,
      default: true,
    },
    // 是否显示下载按钮
    showDownload: {
      type: Boolean,
      default: true,
    },
  },
  data() {
    return {
      currentIndex: this.defaultIndex,
      scaleValues: [], // 记录每个图片的缩放比例
      maxScaleValues: [], // 记录每个图片的最大缩放比例
      isScaling: false, // 是否正在缩放
      initialDistance: 0, // 记录双指触摸的初始距离
      lastTapTime: 0, // 记录上一次点击时间
      windowWidth: 0, // 窗口宽度
      windowHeight: 0, // 窗口高度
    };
  },
  created() {
    // 获取设备屏幕尺寸
    const systemInfo = uni.getSystemInfoSync();
    this.windowWidth = systemInfo.windowWidth;
    this.windowHeight = systemInfo.windowHeight;
  },
  watch: {
    visible(newVal) {
      if (newVal) {
        this.onOpen();
      } else {
        this.onClose();
      }
    },
    images() {
      this.scaleValues = new Array(this.images.length).fill(1);
    },
    defaultIndex(newVal) {
      this.currentIndex = newVal;
    },
  },
  methods: {
    onOpen() {
      // 初始化缩放比例
      this.scaleValues = new Array(this.images.length).fill(1);
      this.maxScaleValues = new Array(this.images.length).fill(8); // 默认最大值
      
      // 禁止页面滚动
      const pageEl =
        document.querySelector("page") || document.querySelector("body");
      if (pageEl) {
        pageEl.style.overflow = "hidden";
        pageEl.style.position = "fixed";
        pageEl.style.width = "100%";
      }
    },
    onClose() {
      // 恢复页面滚动
      const pageEl =
        document.querySelector("page") || document.querySelector("body");
      if (pageEl) {
        pageEl.style.overflow = "";
        pageEl.style.position = "";
        pageEl.style.width = "";
      }

      // 重置缩放值
      this.scaleValues = new Array(this.images.length).fill(1);
    },
    close() {
      this.$emit("close");
    },
    closePreviewOnBg() {
      this.close();
    },
    onSwiperChange(e) {
      this.currentIndex = e.detail.current;
      this.$emit("change", this.currentIndex);
    },
    touchStart(event, index) {
      // 记录触摸开始时的信息
      if (event.touches.length >= 2) {
        // 双指触摸
        this.isScaling = true;
        this.initialDistance = this.getDistance(
          event.touches[0].clientX,
          event.touches[0].clientY,
          event.touches[1].clientX,
          event.touches[1].clientY,
        );
      } else {
        // 单指触摸
        this.isScaling = false;
      }
    },
    touchMove(event, index) {
      if (event.touches.length >= 2 && this.isScaling) {
        // 计算当前两指间距离
        const currentDistance = this.getDistance(
          event.touches[0].clientX,
          event.touches[0].clientY,
          event.touches[1].clientX,
          event.touches[1].clientY,
        );

        // 计算缩放比例变化
        const scale = currentDistance / this.initialDistance;

        // 更新缩放值，限制在合理范围内 (0.5 到 5)
        let newScale = (this.scaleValues[index] || 1) * scale;
        newScale = Math.min(Math.max(newScale, 0.5), this.maxScaleValues[index]);

        // 保存当前缩放值
        this.$set(this.scaleValues, index, newScale);

        // 重置初始距离，防止缩放过快
        this.initialDistance = currentDistance;
      }
    },
    touchEnd() {
      this.isScaling = false;
    },
    handleTap(event, index) {
      const now = new Date().getTime();
      const tapLength = now - this.lastTapTime;
      
      // 双击检测 (300ms内的两次点击视为双击)
      if (tapLength < 300 && tapLength > 0) {
        // 双击时切换缩放状态
        if (this.scaleValues[index] > 1.5) {
          // 如果已经放大，则缩小回原始大小
          this.$set(this.scaleValues, index, 1);
        } else {
          // 否则放大到计算的最大尺寸
          const maxScale = this.maxScaleValues[index] || 2;
          this.$set(this.scaleValues, index, maxScale);
        }
        this.isScaling = false;
        event.stopPropagation(); // 阻止事件冒泡
      } else {
        // 设置延时，以区分单击和双击
        setTimeout(() => {
          // 如果300ms内没有第二次点击，则视为单击，关闭预览
          const newNow = new Date().getTime();
          if (newNow - this.lastTapTime >= 300) {
            // 如果已放大，先恢复原始大小
            if (this.scaleValues[index] > 1) {
              this.$set(this.scaleValues, index, 1);
            } else {
              // 否则关闭预览
              this.close();
            }
          }
        }, 300);
      }
      
      this.lastTapTime = now;
    },
    onImageLoad(event, index) {
      // 获取图片的原始宽高
      uni.getImageInfo({
        src: this.images[index],
        success: (res) => {
          const imgWidth = res.width;
          const imgHeight = res.height;
          
          // 计算图片需要的缩放倍数以适应屏幕
          let maxScale = 1;
          
          // 如果图片比屏幕小，计算放大到填满屏幕所需的倍数
          const screenRatio = this.windowWidth / this.windowHeight;
          const imgRatio = imgWidth / imgHeight;
          
          if (imgRatio > screenRatio) {
            // 图片宽度适配屏幕
            maxScale = (this.windowWidth * 0.98) / (imgWidth * (imgWidth / this.windowWidth));
          } else {
            // 图片高度适配屏幕
            maxScale = (this.windowHeight * 0.98) / (imgHeight * (imgHeight / this.windowHeight));
          }
          
          // 设置最小为2倍，最大为8倍
          maxScale = Math.max(Math.min(maxScale * 2, 8), 2);
          this.$set(this.maxScaleValues, index, maxScale);
          
          console.log(`图片${index}最大缩放比例: ${maxScale}`);
        },
        fail: (err) => {
          console.error('获取图片信息失败:', err);
          this.$set(this.maxScaleValues, index, 5); // 默认最大5倍
        }
      });
    },
    // 计算两点之间的距离
    getDistance(x1, y1, x2, y2) {
      const dx = x2 - x1;
      const dy = y2 - y1;
      return Math.sqrt(dx * dx + dy * dy);
    },
    downloadImage() {
      const currentImage = this.images[this.currentIndex];
      this.$emit("download", currentImage, this.currentIndex);

      // 默认下载行为，可以被覆盖
      let data = {
        imageUrl: currentImage,
      };
      switch (uni.getSystemInfoSync().platform) {
        case "android":
          window.AndroidBridge.savePictureForUrl(JSON.stringify(data));
          break;
        case "ios":
          window.webkit.messageHandlers.savePictureForUrl.postMessage(data);
          break;
        default:
          console.log("运行在开发者工具上");
          uni.saveImageToPhotosAlbum({
            filePath: currentImage,
            success: function () {
              uni.showToast({ title: "保存成功", icon: "success" });
            },
            fail: function () {
              uni.showToast({ title: "保存失败", icon: "none" });
            },
          });
          break;
      }
    },
  },
};
</script>

<style lang="scss" scoped>
.image-preview {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.8);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  z-index: 1003;
  padding: 20rpx;
  /* 防止滑动穿透 */
  touch-action: none;
  overflow: hidden;
}

.preview-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  padding: 20rpx;
  box-sizing: border-box;
  color: #fff;
  font-size: 36rpx;
}

.preview-close {
  width: 60rpx;
  height: 60rpx;
  line-height: 60rpx;
  text-align: center;
  font-size: 40rpx;
  color: #fff;
}

.preview-swiper {
  width: 100%;
  height: 80%;
  border-radius: 20rpx;
  overflow: hidden;
}

.zoom-container {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.preview-image {
  width: 100%;
  height: 100%;
  transform-origin: center center;
}

.preview-footer {
  display: flex;
  justify-content: end;
  align-items: center;
  width: 100%;
  padding: 20rpx;
  box-sizing: border-box;
  font-size: 24rpx;
}

.download-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  color: #fff;
}
</style>
